﻿using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using System.Text;

namespace Arroguella.Entities
{
    /// <summary>
    /// An Entity is any object or creature or element that can exist on
    /// the GameMap or in an inventory.
    /// It is the superclass of all such objects.
    /// </summary>
    public class Entity
    {
        #region Constructor

        public Entity(string name, char symbol, Color color)
        {
            Name = name;
            Symbol = symbol;
            Color = color;

            Components = new List<EntityComponent>();
        }

        #endregion

        #region Events
        #endregion

        #region Methods

        /// <summary>
        /// Adds a component to the list of this Entity's components,
        /// and sets the component's parent as this Entity.
        /// </summary>
        /// <param name="component"></param>
        public void AddComponent(EntityComponent component)
        {
            if (!Components.Contains(component))
            {
                Components.Add(component);
                component.Parent = this;
            }
        }

        /// <summary>
        /// Simply removes a component from this Entity's list of components.
        /// </summary>
        public void RemoveComponent(EntityComponent component)
        {
            if (Components.Contains(component))
            {
                Components.Remove(component);
            }
        }

        #endregion

        #region Properties

        /// <summary>
        /// The name of the Entity.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// The symbol used to represent the Entity on the map.
        /// </summary>
        public char Symbol { get; set; }

        /// <summary>
        /// The color used to draw the Entity on the map.
        /// </summary>
        public Color Color { get; set; }

        /// <summary>
        /// The weight of the item, if any, in kg
        /// </summary>
        public float Weight { get; set; }

        /// <summary>
        /// Whether or not the Player can see the Entity on the map.
        /// </summary>
        public bool IsVisible { get; set; }

        /// <summary>
        /// Whether or not the Player can occupy the same Tile as the Entity on the map.
        /// </summary>
        public bool IsBlocking { get; set; }

        /// <summary>
        /// Whether or not the Entity is part of the environment on the map.
        /// An Environmental Entity cannot be picked up; it is essentially part of the map.
        /// </summary>
        public bool IsEnvironmental { get; set; }

        public List<EntityComponent> Components { get; set; }

        /// <summary>
        /// Whether or not this Entity is capable of storage / inventory
        /// </summary>
        public bool IsStorageEntity
        {
            get { return Components.OfType<StorageEntityComponent>().Any(); }
        }

        /// <summary>
        /// If one exists, returns the StorageEntityComponent.
        /// Otherwise, returns null.
        /// </summary>
        public StorageEntityComponent Storage
        {
            get { return Components.OfType<StorageEntityComponent>().FirstOrDefault(); }
        }

        /// <summary>
        /// Whether or not the Entity is currently held or equipped by the player.
        /// If true, then we have an EquippedSlot listed.
        /// </summary>
        public bool IsEquipped { get { return !string.IsNullOrEmpty(EquippedSlot); } }

        /// <summary>
        /// The slot in which the Entity is currently equipped.
        /// </summary>
        public string EquippedSlot { get; set; }

        protected string description;
        /// <summary>
        /// Detailed description of the equipment, if applicable.
        /// Otherwise, just the name and any relevant stats.
        /// </summary>
        public virtual string Description
        {
            get
            {
                if (string.IsNullOrEmpty(description))
                {
                    return Stats;
                }
                else
                {
                    return Stats + "\n" + description;
                }
            }
            set { description = value; }
        }

        public virtual string Stats
        {
            get
            {
                StringBuilder stats = new StringBuilder();
                stats.AppendLine(Name);
                if (IsEquipped)
                {
                    stats.AppendLine(string.Format("Equipped to: {0}", EquippedSlot));
                }
                stats.AppendLine(string.Format("Weight: {0}kg", Weight));
                if (IsStorageEntity)
                {
                    stats.AppendLine(string.Format("Storage capacity: {0}kg", Storage.WeightLimit));
                }

                return stats.ToString();
            }
        }

        #endregion
    }
}
